﻿Tracking3DApp = function() {
    Sim.App.call(this);
  
};

Tracking3DApp.prototype = new Sim.App();

var container, controls, clock, pointSpheres, stats, trackings, axis, plane, extremeVs, allPoints, gui, effectController, saveObject,
    renderer, root;

var EffectController = function () {
    this.X坐标透明度 = 0;
    this.Y坐标透明度 = 0;
    this.Z坐标透明度 = 0;
    this.坐标字体 = 1;
    this.半径 = 1;
    this.线径 = 0.1;
    this.颜色 = [255, 0, 0];
    this.阴影颜色 = [0xf9, 0xff, 0x99];
    this.第一视角 = false;
    this.倾斜 = true;
    this.阴影Z = true;
    this.阴影Y = true;
    this.阴影X = true;
    this.背景颜色 = [0x00, 0x80, 0x80];
    this.FPS = true;
    this.表格数据 = false;
    this.表格数据宽 = 300;
    this.表格数据高 = 600;
    this.投影 = false;
    this.YZ背景 = [0x00, 0x80, 0x80];
    this.XY背景 = [0x00, 0x80, 0x80];
    this.XZ背景 = [0x00, 0x80, 0x80];
};
Tracking3DApp.prototype.init = function (param) {
    effectController = new EffectController();
    pointSpheres = [];
    trackings = [];
    extremeVs = [];
    Sim.App.prototype.init.call(this, param);
    renderer = this.renderer;
    root = this.root;
    container = param.container;
    container.focus();
    
    this.renderer.setClearColor(getThreeColor(effectController.背景颜色));
    stats = new Stats();
    stats.domElement.style.position = 'absolute';
    stats.domElement.style.top = '0';
    container.appendChild(stats.domElement);

    this.createController();

    // Let there be light!
    var sun = new Sun();
    sun.init();
    
    this.addObject(sun);

    this.root.rotation.z += Math.PI / 16;
    this.root.rotation.y += Math.PI / 3;
    this.root.rotation.x += Math.PI / 16;
    this.root.position.y -= 60;
    this.root.position.x -= 30;
    camera.position.set(0, 0, 200);
};

Tracking3DApp.prototype.show = function (groupPoints) {
    extremeVs = [];
    allPoints = groupPoints;
    var i,key,list;

    Tracking3DApp.Geometries = [];
    this.doDispose(axis);
    this.doDispose(plane);
    
    if (pointSpheres) {
        for (i = 0; i < pointSpheres.length; i++) {
            this.doDispose(pointSpheres[i]);
        }
        pointSpheres = [];
    }
    if (trackings) {
        for (i = 0; i < trackings.length; i++) {
            this.doDispose(trackings[i]);
        }
        trackings = [];
    }
    
    if (!gui) {
        this.createGUI();
    }
   
    this.renderer.setClearColor(getThreeColor(effectController.背景颜色));
    
    var material = new THREE.MeshPhongMaterial({ color: getThreeColor(effectController.颜色) });
    for ( key in groupPoints) {
         list = groupPoints[key];
        if (!groupPoints[key].length) {
            continue;
        }

        var minV, maxV;
        minV = new THREE.Vector3(list[0].X, list[0].Y, list[0].Z);
        maxV = minV.clone();
        for (i = 0; i < list.length; i++) {
            list[i].Vector3 = new THREE.Vector3(list[i].X, list[i].Y, list[i].Z);
            minV.min(list[i].Vector3);
            maxV.max(list[i].Vector3);
        }
        minV.addScalar(-Tracking3DApp.STEP);
        minV.x += Tracking3DApp.STEP;
        maxV.addScalar(Tracking3DApp.STEP);

        extremeVs.push({ key: key, max: maxV, min: minV });
        
        this.createTrackingLine(key, list, material);
    }
    for (key in groupPoints) {
        this.createPlanes(key);
        break;
    }
    this.createAxis(extremeVs);
    this.createProjection();
};

Tracking3DApp.prototype.lookAtZero = function () {
    this.createController();
};

Tracking3DApp.prototype.createAxis = function () {
    var maxV = new THREE.Vector3(-1000, -1000, -1000);
    var minV = new THREE.Vector3(1000, 1000, 1000);
    for (var i = 0; i < extremeVs.length; i++) {
        maxV.max(extremeVs[i].max);
        minV.min(extremeVs[i].min);
    }
    axis = new Axis();
    axis.init(maxV, minV, Tracking3DApp.STEP, effectController);
    this.addObject(axis);
};

Tracking3DApp.prototype.createTrackingLine = function (Id, points,material) {
    var geometry = new THREE.SphereGeometry(effectController.半径);
    var vectors = [];
    for (var i = 0; i < points.length; i++) {
        var pointSphere = new PointSphere();
        pointSphere.init(points[i], geometry, material);
        this.addObject(pointSphere);
        pointSphere.subscribe('mouseMove', this, this.onPointSphereMouseMove);
        pointSphere.subscribe('mouseOut', this, this.onPointSphereMouseOut);
        pointSphere.subscribe('mouseDown', this, this.onPointSphereMouseDown);
        pointSphere.subscribe('mouseUp', this, this.onPointSphereMouseUp);
        pointSpheres.push(pointSphere);
        vectors.push(points[i].Vector3);
    }
    var tracking = new Tracking();
    tracking.init(Id, vectors, material, effectController.线径);
    this.addObject(tracking);
    trackings.push(tracking);
};

Tracking3DApp.prototype.createPlanes = function (Id) {

    this.doDispose(plane);
    
    var extremeV = null;
    var maxV = new THREE.Vector3(-1000, -1000, -1000);
    var minV = new THREE.Vector3(1000, 1000, 1000);
    for (var i = 0; i < extremeVs.length; i++) {
        maxV.max(extremeVs[i].max);
        minV.min(extremeVs[i].min);
        if (Id === extremeVs[i].key) {
            extremeV = extremeVs[i];
        }
    }
    
    for (var key in allPoints) {
        var list = allPoints[key];
        if (key != Id || !allPoints[key].length) {
            continue;
        }
        
        if (extremeV) {
            plane = new Plane();
            plane.init(new THREE.Vector3(extremeV.min.x, minV.y, extremeV.min.z), extremeV.max, Tracking3DApp.STEP, list, getThreeColor(effectController.阴影颜色), effectController.阴影X, effectController.阴影Y, effectController.阴影Z);
            this.addObject(plane);
            break;
        }
    }
};


Tracking3DApp.prototype.createGUI = function () {

    gui = new dat.GUI({ autoPlace: false });
    gui.useLocalStorage = true;
    gui.closed = true;
    gui.remember(effectController);
//    saveObject = gui.getSaveObject();
    var e = $(gui.domElement).css("opacity", "0.9").css( "position", "absolute").css( "top", "0").css("right",'0');
    $(container).append(e);
    
    var h = gui.addFolder("坐标系");
    h.add(effectController, "X坐标透明度", 0, 1.0);
    h.add(effectController, "Y坐标透明度", 0, 1.0);
    h.add(effectController, "Z坐标透明度", 0, 1.0);
    h.add(effectController, "坐标字体", 1, 5);
    h = gui.addFolder("轨迹");
    h.add(effectController, "半径", 0.5, 2);
    h.add(effectController, "线径", 0.1, 0.5);
    h.addColor(effectController, '颜色');
    h = gui.addFolder("阴影");
    h.addColor(effectController, '阴影颜色');
    h.add(effectController, '阴影X');
    h.add(effectController, '阴影Y');
    h.add(effectController, '阴影Z');
    h = gui.addFolder("背景");
    h.addColor(effectController, '背景颜色');
    h.add(effectController, 'FPS');
    h.add(effectController, '表格数据');
    h.add(effectController, '表格数据宽',100,800);
    h.add(effectController, '表格数据高',500,1000);
    h = gui.addFolder("投影");
    h.add(effectController, '投影').onChange(this.createProjection);
    h.addColor(effectController, 'YZ背景');
    h.addColor(effectController, 'XY背景');
    h.addColor(effectController, 'XZ背景');
//    h = gui.addFolder("控制");

//    h.add(effectController, "第一视角").onChange(this.createController);
//    h.add(effectController, "倾斜").onChange(function (value) {
//        if (value) {
//            root.rotation.x += Math.PI / 4;
//            root.rotation.y -= Math.PI / 4;
//        } else {
//            root.rotation.x = 0;
//            root.rotation.y = 0;
//            root.rotation.z = 0;
//        }
//    });
};

Tracking3DApp.prototype.createProjection = function() {
    var check = effectController.投影;
    if (check) {
        $("#chartContainer").show();
        var yzdata = [] ,xydata = [],xzdata = [];
        for (key in allPoints) {
            var list = allPoints[key];
            if (!allPoints[key].length) {
                continue;
            }
            var yz = [], xy = [], xz = [];

            for (var i = 0; i < list.length; i++) {
                var v = list[i].Vector3;
                yz.push({ x: v.y, y: v.z });
                xy.push({ x: v.x, y: v.y });
                xz.push({ x: v.x, y: v.z });
            }
            yzdata.push({ type: "line", dataPoints: yz });
            xydata.push({ type: "line", dataPoints: xy });
            xzdata.push({ type: "line", dataPoints: xz });
        }

        var chart = new CanvasJS.Chart("yzChart", {
            backgroundColor: getColor(effectController.YZ背景),
            zoomEnabled: false,
            title: {
                text: "Y-Z面投影"
            },
            axisY: {
                title: "Z轴"
            },
            axisX: {
                title: "Y轴",
            },
            legend: {
                horizontalAlign: "right",
                verticalAlign: "center"
            },
            data: yzdata,  // random generator below
        });

        chart.render();

        var chart = new CanvasJS.Chart("xyChart", {
            backgroundColor: getColor(effectController.XY背景),
            zoomEnabled: false,
            title: {
                text: "X-Y面投影"
            },
            axisY: {
                title: "Y轴"
            },
            axisX: {
                title: "X轴",
            },
            legend: {
                horizontalAlign: "right",
                verticalAlign: "center"
            },
            data: xydata,  // random generator below
        });
        chart.render();

       
        var chart = new CanvasJS.Chart("xzChart", {
            backgroundColor: getColor(effectController.XZ背景),
            zoomEnabled: false,
            title: {
                text: "X-Z面投影"
            },
            axisY: {
                title: "Z轴"
            },
            axisX: {
                title: "X轴",
            },
            legend: {
                horizontalAlign: "right",
                verticalAlign: "center"
            },
            data: xzdata,  // random generator below
        });
        chart.render();
       
    } else {
        $("#chartContainer").hide();
    }
};

Tracking3DApp.prototype.createProjection = function() {
    var check = effectController.投影;
    if (check) {
        $("#chartContainer").show();
        var yzdata = [] ,xydata = [],xzdata = [];
        for (key in allPoints) {
            var list = allPoints[key];
            if (!allPoints[key].length) {
                continue;
            }
            var yz = [], xy = [], xz = [];

            for (var i = 0; i < list.length; i++) {
                var v = list[i].Vector3;
                yz.push({ x: v.y, y: v.z });
                xy.push({ x: v.x, y: v.y });
                xz.push({ x: v.x, y: v.z });
            }
            yzdata.push({ type: "line", dataPoints: yz });
            xydata.push({ type: "line", dataPoints: xy });
            xzdata.push({ type: "line", dataPoints: xz });
        }

        var chart = new CanvasJS.Chart("yzChart", {
            backgroundColor: getColor(effectController.YZ背景),
            zoomEnabled: false,
            title: {
                text: "Y-Z面投影"
            },
            axisY: {
                title: "Z轴"
            },
            axisX: {
                title: "Y轴",
            },
            legend: {
                horizontalAlign: "right",
                verticalAlign: "center"
            },
            data: yzdata,  // random generator below
        });

        chart.render();

        var chart = new CanvasJS.Chart("xyChart", {
            backgroundColor: getColor(effectController.XY背景),
            zoomEnabled: false,
            title: {
                text: "X-Y面投影"
            },
            axisY: {
                title: "Y轴"
            },
            axisX: {
                title: "X轴",
            },
            legend: {
                horizontalAlign: "right",
                verticalAlign: "center"
            },
            data: xydata,  // random generator below
        });
        chart.render();

       
        var chart = new CanvasJS.Chart("xzChart", {
            backgroundColor: getColor(effectController.XZ背景),
            zoomEnabled: false,
            title: {
                text: "X-Z面投影"
            },
            axisY: {
                title: "Z轴"
            },
            axisX: {
                title: "X轴",
            },
            legend: {
                horizontalAlign: "right",
                verticalAlign: "center"
            },
            data: xzdata,  // random generator below
        });
        chart.render();
       
    } else {
        $("#chartContainer").hide();
    }
};


Tracking3DApp.prototype.createController = function () {
    controls = null;
    if (effectController.第一视角) {
   
        controls = new THREE.FirstPersonControls(camera, renderer.domElement);
        controls.movementSpeed = 25;
        controls.lookSpeed = 0.01;

        // Don't allow tilt up/down
        controls.lookVertical = false;
        if (!clock) {
            clock = new THREE.Clock();
        }
    } else {
        controls = new THREE.TrackballControls(camera, renderer.domElement);
//        controls = new THREE.OrbitControls(camera, renderer.domElement);
    }
};



Tracking3DApp.prototype.update = function () {
    Sim.App.prototype.update.call(this);
 
    if (effectController.FPS) {
        $(stats.domElement).show();
        stats.update();
    } else {
        $(stats.domElement).hide();
    }
   
    if (this.isDrag) {
        controls.noRotate = true;
    } else {
        controls.noRotate = false;
        if (!controls) {
            this.createController();
        }
        this.dragStartPosition = null;
    }
    if (controls) {
        if ( effectController.第一视角) {
            controls.update(clock.getDelta());
        } else {
            controls.update();
        }
    }
};



Tracking3DApp.prototype.onPointSphereMouseDown = function (x, y,Id) {
    this.isDrag = true;
    this.dragId = Id;
};

Tracking3DApp.prototype.onPointSphereMouseMove = function (x, y, tips) {
    var left = x + 20;
    var top = y;
    var xEdge = this.container.offsetWidth;
    var yEdge = this.container.offsetHeight;
    if (xEdge - x < $("#tips").outerWidth()) {
        left = x - 20 - $("#tips").outerWidth();
    }
    if (yEdge - y < $("#tips").outerHeight()) {
        top = y - $("#tips").outerHeight();
    }

    $("#tips").html(tips);
    $("#tips").css({ left: left, top: top }).show();
};

Tracking3DApp.prototype.onPointSphereMouseOut = function (x, y) {
    $("#tips").hide();
};

var redrawingAxis = false;  //是否重绘坐标系。
Tracking3DApp.prototype.handleMouseMove = function(x, y) {
    if (this.isDrag) {

        var pos = this.getViewPortVector(x, y);
        
        if (!this.dragStartPosition) {
            this.dragStartPosition = pos.clone();
        }
        var d= pos.clone().sub(this.dragStartPosition);

        var extremeV = null;
        for (var j = 0; j < extremeVs.length; j++) {
            if (extremeVs[j].key == this.dragId) {
                extremeV = extremeVs[j];
                break;
            }
        }

        var maxV = new THREE.Vector3(-1000, -1000, -1000);
        var minV = new THREE.Vector3(1000, 1000, 1000);
        for (var i = 0; i < pointSpheres.length; i++) {
            var point = pointSpheres[i];
            if (point.Id === this.dragId) {
                var v = point.move(d.y, d.x);
                maxV.max(v);
                minV.min(v);
            }
        }

        if (extremeV) {
            minV.addScalar(-Tracking3DApp.STEP);
            minV.x += Tracking3DApp.STEP;
            maxV.addScalar(Tracking3DApp.STEP);

            if (extremeV.max.equals(maxV) && extremeV.min.equals( minV)) {
                redrawingAxis = false;
            } else {
                extremeV.max = maxV;
                extremeV.min = minV;
                redrawingAxis = true;
            }
        }

        for (i = 0; i < trackings.length; i++) {
            var tracking = trackings[i];
            if (tracking.Id === this.dragId) {
                tracking.move(d.y, d.x);
            }
        }

        this.dragStartPosition = pos.clone();
    }
};

Tracking3DApp.prototype.handleMouseDown = function () {
    
    if (effectController.表格数据 &&this.isDrag && this.dragId) {
        //显示数据
        $("#dataContainer").empty();
        $("#dataContainer").css("width", effectController.表格数据宽);
        for (var key in allPoints) {
            if (key == this.dragId) {
                var list = allPoints[key];
                if (list.length) {
                    $("#dataContainer").show();
                    $("#dataContainer").append("<table cellpadding='0' cellspacing='0' border='0' class='display' id='example'></table>");
                    
                    var dataSet = [];
                    for (var i = 0; i < list.length; i++) {
                        var p = list[i];
                        dataSet.push([p.Date, p.Depth.toFixed(2), p.Azimuth.toFixed(2), p.Inclination.toFixed(2), p.X.toFixed(2), p.Y.toFixed(2), p.Z.toFixed(2), p.Rotation.toFixed(2)]);
                    }
                    var table = $('#example').dataTable({
                        //                        "scrollX": true,
                        scrollY: effectController.表格数据高,
                        scrollCollapse: true,
                        "paging":false,
                        "data": dataSet,
                        "ordering": false,
                        "info": false,
                        "searching": false,
                        "iDisplayLength": 15,
                        "dom": '<"top"i>rt<"bottom"flp><"clear">',
                        "columns": [
                            { "title": "时间" },
                            { "title": "深度" },
                            { "title": "俯仰角" },
                            { "title": "方位角", "class": "center" },
                            { "title": "X坐标", "class": "center" },
                            { "title": "Y坐标", "class": "center" },
                            { "title": "Z坐标", "class": "center" },
                            { "title": "翻滚角度", "class": "center" }
                        ]
                    });
                    
//                    new $.fn.dataTable.FixedHeader(table);
                }
                break;
            }
        }
    } else {
        //隐藏数据
        $("#dataContainer").hide();
       
    }
};


Tracking3DApp.prototype.handleDbClick = function(event) {
    if (!this.isDrag) {
        //双击隐藏阴影
        this.doDispose(plane);
    }
};

Tracking3DApp.prototype.handleMouseUp = function () {
    if (this.isDrag) {
        THREE.THREEDTextHelper.Geometries = [];
       
        this.doDispose(plane);
        this.isDrag = false;
        
        if (redrawingAxis) {
            Tracking3DApp.Geometries = [];
            this.doDispose(axis);
            this.createAxis();

            redrawingAxis = false;
            this.createProjection();
        }
       
        this.createPlanes(this.dragId);
    }
};


//步履,每10作为坐标轴的1.
Tracking3DApp.STEP = 10;

// Custom Sun class
Sun = function() {
    Sim.Object.call(this);
};

Sun.prototype = new Sim.Object();

Sun.prototype.init = function() {
    // Create a point light to show off the earth - set the light out back and to left a bit
    var group = new THREE.Object3D();
    this.setObject3D(group);
    
    var lightA = new THREE.PointLight(0xffffff, 1, 10000);
    lightA.position.set(1000, 1000, 1000);
    group.add(lightA);
    
    var lightB = new THREE.PointLight(0xffffff, 1, 10000);
    lightB.position.set(-1000, -1000, -1000);
    group.add(lightB);
};


Tracking3DApp.Geometries = [];



/*****************************/

function getThreeColor (effectColor) {
    if (effectColor.indexOf('#') >= 0) {
        return effectColor;
    } else {
        var r = effectColor[0] / 255;
        var g = effectColor[1] / 255;
        var b = effectColor[2] / 255;

        return new THREE.Color(r, g, b);
    }

}

function getColor (effectColor) {
    if (effectColor.indexOf('#') >= 0) {
        return effectColor;
    } else {
        var r =effectColor[0];
        var g =effectColor[1];
        var b =effectColor[2];

        return '#' + byte2Hex(r) + byte2Hex(g) + byte2Hex(b);
    }
}

function byte2Hex(n) { var nybHexString = "0123456789ABCDEF"; return String(nybHexString.substr((n >> 4) & 0x0F, 1)) + nybHexString.substr(n & 0x0F, 1); }
/*****************************/